#include "graphics/oriented_bounding_box.h"

#include "graphics/axis_aligned_bounding_box.h"
#include "graphics/bounding_sphere.h"

namespace graphics{

bool OrientedBoundingBox::Overlaps(const BoundingVolume * other) const { return other->OverlapWith(this); }

bool OrientedBoundingBox::OverlapWith(const AxisAlignedBoundingBox * other) const {
    Vector3 line = other->GetCenter() - center_;
    float distance = line.length();
     
    float closest_point_distance = abs(cml::dot(GetHalfDimension(), line)) / distance;
    
    Vector3 other_dimension = other->GetHalfDimension();        
    float other_closest_point_distance = abs(cml::dot(other_dimension, line)) / distance;

    distance -= closest_point_distance;
    distance -= other_closest_point_distance;

    if(distance <= BoundingVolume::kOverlapTolerance)
        return true;
    else return false;
}

bool OrientedBoundingBox::OverlapWith(const OrientedBoundingBox * other) const {
    Vector3 line = other->GetCenter() - center_;
    float distance = line.length();
     
    float closest_point_distance = abs(cml::dot(GetHalfDimension(), line)) / distance;
    
    Vector3 other_dimension = other->GetHalfDimension();        
    float other_closest_point_distance = abs(cml::dot(other_dimension, line)) / distance;

    distance -= closest_point_distance;
    distance -= other_closest_point_distance;

    if(distance <= BoundingVolume::kOverlapTolerance)
        return true;
    else return false;
}

bool OrientedBoundingBox::OverlapWith(const BoundingSphere * other) const {
    Vector3 line = other->GetCenter() - center_;
    float distance = line.length();
    
             
    float closest_point_distance = abs(cml::dot(GetHalfDimension(), line)) / distance;

    distance -= closest_point_distance;
    distance -= other->GetRadius();

    if(distance <= BoundingVolume::kOverlapTolerance)
        return true;
    else return false;
}

} //namespace graphics